home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
14642
/
14642.xpi
/
chrome
/
modules
/
tracker.js
< prev
Wrap
Text File
|
2009-10-20
|
22KB
|
599 lines
/* Copyright 2009, Boomtango.com. All Rights Reserved. */
/* tracker.js
* Responsible for tracking user behavior and sending to db
*/
var EXTERNAL_TRACKERS = ['shopping', 'wikipedia', 'search', 'bookmark', 'contact', 'video'];
var EXPORTED_SYMBOLS = ["boomtangoTracker"];
function CustomCategory(name, keywords, regex) {
this.name = name;
this.name_plural = name;
this.keywords = keywords;
this.regex = regex;
this.color = boomtangoTracker.app.generateColor();
this.id = "custom." + encodeURIComponent(name);
this.description = boomtangoTracker.app.getString("tracker.custom", keywords);
}
CustomCategory.prototype = {
onLoadTracks: function(url, doc, referrer, content){
var results = [];
if(content && content.length){
if(this.regex){
if(content.match(this.keywords)){
results.push({
type: this.id
});
}
} else {
var a = this.keywords.split(',');
var len = a.length;
for(var x = 0; x < len; x++){
if(content.indexOf(a[x]) >= 0){
results.push({
type: this.id
});
break;
}
}
}
}
return results;
}
};
var boomtangoTracker = {
cc: Components.classes,
ci: Components.interfaces,
types: {
web: {
name: "Website",
name_plural: "Websites",
color: "#289f65",
isInternal: true,
preview: function(doc, node, data){
var nopreview = true;
if(data.preview && data.preview.length){
var src = this.app.getThumb(parseInt(data.preview));
if(src.length){
var image = doc.createElement('image');
image.setAttribute("src", src);
image.className = "webthumb";
node.appendChild(image);
nopreview = false;
}
}
if(nopreview){
var vbox = doc.createElement('vbox');
var spacer = doc.createElement('spacer');
spacer.setAttribute('flex', '100');
spacer.setAttribute('height', '80');
vbox.appendChild(spacer);
vbox.className = "nothumb";
vbox.setAttribute("style", "width: 240px");
var label = doc.createElement('label');
label.setAttribute('value', this.app.getString('history.nopreview'));
label.className = 'nopreview';
vbox.appendChild(label);
spacer = doc.createElement('spacer');
spacer.setAttribute('flex', '100');
spacer.setAttribute('height', '80');
vbox.appendChild(spacer);
node.appendChild(vbox);
}
}
}
},
loadCategoryTrackers: function(){
var list = this.app.getCustomCategoryList();
var len = list.length;
for(var x=0; x < len; x++){
var item = list[x];
this.createCategoryTracker(item.name, item.keywords, item.regex, true);
}
},
loadCustomTrackers: function(){
var file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsIFile);
file.append("boomtango");
file.append("trackers");
var entries = file.directoryEntries;
var jsregex = /^(.*)\.bct$/;
var loader = Components.classes
["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
var ios = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
while(entries.hasMoreElements()){
var entry = entries.getNext();
var jsfile = entry.QueryInterface(Components.interfaces.nsIFile);
var results = jsregex.exec(jsfile.leafName);
if(results){
this.app.log("tracker::loadCustom (" + jsfile.leafName + ")");
var jsurl = ios.newFileURI(jsfile).spec;
try {
var newtype = {};
loader.loadSubScript(jsurl, newtype);
if(newtype.module){
var id = "import." + results[1];
this.types[id] = newtype.module;
this.types[id].id = id;
this.addMemberFuncs(this.types[id]);
if(newtype.module.init){
newtype.module.init(this.app.getTrackerData(id));
}
}
} catch(e){
this.app.log("error loading custom js: " + e.message);
}
}
}
},
enableTracker: function(type, doEnable){
if(this.app.getTrackerEnabled(type) != doEnable){
this.app.setTrackerEnabled(type, doEnable);
this.observer.notifyObservers(null, "boomtango-tracker-" + (doEnable ? "add" : "remove"), type);
}
},
createCategoryTracker: function(name, keywords, regex, noAppUpdate){
this.app.log("tracker::createCategory(" + name + ", (" + keywords + "), "
+ regex);
var cat = new CustomCategory(name, keywords, regex);
this.types[cat.id] = cat;
if(!noAppUpdate){
this.app.addCustomCategory(name, keywords, regex);
this.observer.notifyObservers(null, "boomtango-tracker-add", cat.id);
}
return cat.id;
},
importTracker: function(importFile){
var id = '????';
var update = false;
var file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsIFile);
file.append("boomtango");
file.append("trackers");
var name = importFile.leafName;
this.app.log("tracker::importTracker (" + name + ")");
try {
var file2 = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsIFile);
file2.append("boomtango");
file2.append("trackers");
file2.append(name);
if(file2.exists()){
update = true;
try {
file2.remove(false);
} catch(e){
this.app.log("error deleting custom js: " + e.message);
}
}
importFile.copyTo(file, name);
file.append(name);
var ios = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
var jsregex = /^(.*)\.bct$/;
var results = jsregex.exec(name);
if(results){
var loader = Components.classes
["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
var jsurl = ios.newFileURI(file).spec;
var newtype = {};
loader.loadSubScript(jsurl, newtype);
if(newtype.module){
var id = "import." + results[1];
this.types[id] = newtype.module;
if(!newtype.module.name_plural){
newtype.module.name_plural = newtype.module.name;
}
this.types[id].id = id;
this.addMemberFuncs(this.types[id]);
if(newtype.module.init){
newtype.module.init(null);
}
this.observer.notifyObservers(null, "boomtango-tracker-add", id);
}
}
} catch(e){
this.app.log("error importing custom js: " + e.message);
}
return update ? '????' : id;
},
addMemberFuncs: function(module){
var app = this.app;
var id = module.id;
var getDataFunc = function(){
return app.getTrackerData(id);
};
var setDataFunc = function(data){
app.setTrackerData(id, data);
};
var log = function(s){
app.log(s);
};
var debug = function(s){
app.debug(s);
};
module.getData = getDataFunc;
module.setData = setDataFunc;
module.app = app;
module.log = log;
module.debug = debug;
},
deleteTracker: function(type){
var a = type.split('.');
if(!a.length){
return;
}
switch(a[0]){
case 'custom':
var name = decodeURIComponent(a[1]);
this.app.removeCustomCategory(name);
var types = this.types;
delete types[type];
this.observer.notifyObservers(null, "boomtango-tracker-remove", type);
break;
case 'import':
var file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsIFile);
file.append("boomtango");
file.append("trackers");
file.append(a[1] + ".bct");
try {
file.remove(false);
} catch(e){
this.app.log("error deleting custom js: " + e.message);
}
var types = this.types;
delete types[type];
this.observer.notifyObservers(null, "boomtango-tracker-remove", type);
break;
}
},
init: function(app){
this.app = app;
this.storage = app.storage;
this.purgatory = {};
this.app.debug("tracker::init");
var types = this.types;
var len = EXTERNAL_TRACKERS.length;
while(len--){
this.app.debug("Adding " + EXTERNAL_TRACKERS[len]);
Components.utils.import("resource://boomtango/trackers/" + EXTERNAL_TRACKERS[len] + ".js", types);
}
this.app.debug("Internal Trackers Loaded");
for(var x in types){
if(types.hasOwnProperty(x) && types[x].isInternal){
types[x].app = this.app;
types[x].name = this.app.getString("type.name." + x);
types[x].name_plural = this.app.getString("type.name_plural." + x);
types[x].description = this.app.getString("type.description." + x);
}
}
this.loadCategoryTrackers();
this.loadCustomTrackers();
var history = this.cc["@mozilla.org/browser/nav-history-service;1"].
getService(this.ci.nsINavHistoryService);
this.observer = this.cc["@mozilla.org/observer-service;1"].
getService(this.ci.nsIObserverService);
history.addObserver(this, false);
this.init = function(){};
},
importBrowserHistoryDone: function(callback){
this.app.log("tracker:importDone");
this._inImport = false;
if(this.importData){
this.importData.containerOpen = false;
delete this.importData;
}
},
importBrowserHistoryDoFTS: function(callback, loadFunc){
this.app.log("tracker:importFTS(" + this.importDataCtr + ")");
var storage = this.storage;
var cont = this.importData;
var len = this.importDataLength;
if(this.importDataCtr >= len){
callback(this.importDataCtr, len, false);
return;
}
var node = cont.getChild(this.importDataCtr);
var title = node.title;
var url = node.uri;
var starttime = Math.round(node.time / 1000);
var self = this;
loadFunc(url, function(doc, thumb){
var content = "";
if(doc){
content = doc.body ? doc.body.textContent : "";
}
var tracks = [
// add a general tab
{
type: "web",
title: node.title,
textContent: "",
preview: thumb.toString()
}
];
var types = this.types;
for( var x in types){
if(types.hasOwnProperty(x)){
var helper = types[x];
if(helper.onLoadTracks && this.app.getTrackerEnabled(x)){
var a = helper.onLoadTracks(url, doc);
for(var x = 0; x < a.length; x++){
tracks.push(a[x]);
}
}
if(helper.onUnloadTracks){
var a = helper.onUnloadTrack(url, doc);
for(var x = 0; x < a.length; x++){
tracks.push(a[x]);
}
}
}
}
var len = tracks.length;
for(var x = 0; x < len; x++){
var t = tracks[x];
if(t.content){
content += " " + t.content;
} else if(t.type == "shopping" && t.redirect_url){
url = t.redirect_url;
}
}
var ftsrowid = storage.addFTS(title, content, starttime,
-1, url);
storage.addTrackers(
url,
title,
ftsrowid,
starttime, starttime,
tracks
);
self.importDataCtr++;
if(self.importDataCtr >= len){
self.importBrowserHistoryDone();
callback(self.importDataCtr, len, false);
} else {
callback(self.importDataCtr, len, true);
}
});
},
importBrowserHistoryDo: function(callback){
this.app.log("tracker::importBrowserHistoryDo");
var storage = this.storage;
var cont = this.importData;
var len = this.importDataLength;
var d = Date.now();
for (; this.importDataCtr < len && Date.now() < d + 100; this.importDataCtr++) {
if(!callback(this.importDataCtr, len)){
this.importBrowserHistoryDone();
return;
}
var node = cont.getChild(this.importDataCtr);
var title = node.title;
var url = node.uri;
var starttime = Math.round(node.time / 1000);
var content = "";
var tracks = [
// add a general tab
{
type: "web",
title: node.title,
textContent: "",
preview: ""
}
];
var types = this.types;
for( var x in types){
if(types.hasOwnProperty(x)){
var helper = types[x];
if(helper.onLoadTracks && this.app.getTrackerEnabled(x)){
var a = helper.onLoadTracks(url);
for(var x = 0; x < a.length; x++){
tracks.push(a[x]);
}
}
if(helper.onUnloadTracks){
var a = helper.onUnloadTracks(url);
for(var x = 0; x < a.length; x++){
tracks.push(a[x]);
}
}
}
}
var tracklen = tracks.length;
for(var x = 0; x < tracklen; x++){
var t = tracks[x];
if(t.content){
content += " " + t.content;
} else if(t.type == "shopping" && t.redirect_url){
url = t.redirect_url;
}
}
var ftsrowid = storage.addFTS(title, content, starttime,
-1, url);
storage.addTrackers(
url,
title,
ftsrowid,
starttime, starttime,
tracks
);
}
if(this.importDataCtr >= len){
this.importBrowserHistoryDone();
return false;
} else {
return true;
}
},
importBrowserHistoryStart: function(){
this.app.debug("tracker::importBrowserHistory");
this._inImport = true;
var historyService =
Components.classes["@mozilla.org/browser/nav-history-service;1"]
.getService(Components.interfaces.nsINavHistoryService);
var options = historyService.getNewQueryOptions();
options.queryType = options.QUERY_TYPE_HISTORY;
options.resultType = options.RESULTS_AS_VISIT;
options.sortingMode = options.SORT_BY_DATE_ASCENDING;
var query = historyService.getNewQuery();
var result = historyService.executeQuery(query, options);
this.importData = result.root;
this.importData.containerOpen = true;
this.importDataCtr = 0;
this.importDataLength = this.importData.childCount;
this.app.debug("import count = " + this.importData.childCount );
},
onPageLoad: function(browserID, doc, thumb, referrer){
var url = doc.location.href;
this.app.log("tracker:onPageLoad (" + url + ")");
var startTime = Date.now();
var tracks = [
// add a general tab
{
type: "web",
title: doc.title,
preview: thumb
}
];
var content = "";
if(doc.body){
var tmpBody = doc.body.cloneNode(true);
Array.prototype.slice.call(
tmpBody.getElementsByTagName('script')
).forEach(function(i) { i.parentNode.removeChild(i);});
content = [tmpBody.textContent.replace(/\s+/g,' '),doc.title].join(' ');
delete tmpBody;
}
var types = this.types;
var trkctr = 0;
for( var x in types){
if(types.hasOwnProperty(x)){
var helper = types[x];
if(helper.onLoadTracks && this.app.getTrackerEnabled(x)){
trkctr++;
var a = helper.onLoadTracks(url, doc, referrer, content);
for(var x = 0; x < a.length; x++){
tracks.push(a[x]);
}
}
}
}
var len = tracks.length;
for(var x = 0; x < len; x++){
var t = tracks[x];
if(t.content){
content += " " + t.content;
} else if(t.type == "shopping" && t.redirect_url){
url = t.redirect_url;
}
}
var data = {
url: url,
browserID: browserID,
tracks: [],
title: doc.title,
ftsrowid: this.storage.addFTS(doc.title, content, startTime, -1, url),
startTime: startTime,
endTime: -1,
inSync: true
};
this.purgatory[browserID + "-" + url] = data;
this.storage.addTrackers(url, data.title, data.ftsrowid,
data.startTime, -1, tracks);
this.observer.notifyObservers(null, "boomtango-visit-add",
data.ftsrowid.toString());
this.app.log("End Page Load: " + trkctr + ", " + (Date.now() - startTime));
},
onPageUnload: function(browserID, doc){
var url = doc.location.href;
var endTime = Date.now();
var tracks = [];
var types = this.types;
for( var x in types){
if(types.hasOwnProperty(x)){
var helper = types[x];
if(helper.onUnloadTracks && this.app.getTrackerEnabled(x)){
var a = helper.onUnloadTracks(url, doc);
for(var x = 0; x < a.length; x++){
tracks.push(a[x]);
}
}
}
}
var data = this.purgatory[browserID + "-" + url];
if(data){
data.endTime = endTime;
this.storage.updateTrackerEnd(url, endTime, data.ftsrowid);
this.storage.addTrackers(url, data.title, data.ftsrowid,
data.startTime, data.endTime, tracks);
this.observer.notifyObservers(null, "boomtango-visit-change",data.ftsrowid.toString());
this.purgatory[browserID + "-" + url] = null;
}
},
QueryInterface: function(iid) {
if (iid.equals(this.ci.nsINavHistoryObserver) ||
iid.equals(this.ci.nsINavHistoryObserver_MOZILLA_1_9_1_ADDITIONS) ||
iid.equals(this.ci.nsISupports)) {
return this;
}
throw Components.result.NS_ERROR_NO_INTERFACE;
},
//nsINavHistoryObserver
onBeforeDeleteURI: function(){},
onDeleteURI: function(uri){
this.storage.deleteTrackersForURL(uri.spec);
this.observer.notifyObservers(null, "boomtango-datachange",
"delete");
},
onClearHistory: function(){},
onBeginUpdateBatch: function(){},
onEndUpdateBatch: function(){},
onPageChanged: function(){},
onPageExpired: function(){},
onTitleChanged: function(){},
onVisit: function(uri){
}
};